#include<queue>
#include <iostream>
#include "task.hpp"
#include <vector>
#include <pthread.h>
const int num=5;
struct threadpooldata
{

  pthread_t pid;
  string threadname;

};
template  <class T>
class threadpool
{
private:
void lock()
{
pthread_mutex_lock(&_mutex);
}
void unlock()
{
pthread_mutex_unlock(&_mutex);

}
void go_sleep()
{
pthread_cond_wait(&_cond,&_mutex);
}
void weakup()
{
 pthread_cond_signal(&_cond);

}
bool isempty()
{
return _st.empty();
}

public:

threadpool(int defaultnum=num)
:_threads(defaultnum)
{
  
  pthread_mutex_init(&_mutex,nullptr);
  pthread_cond_init(&_cond,nullptr);
}


void start()
{
    int sz=_threads.size();
    for(int i=0;i<sz;i++)
       {
          _threads[i].threadname="thread"+to_string(i);
          pthread_create(&_threads[i].pid,nullptr,fun,this);
       
       }

}
static void*fun(void*argv)
{
   threadpool<T>*ret=static_cast<threadpool<T>*>(argv);
   
   while(1)
   {  ret->lock();
     while( ret->isempty())
     {
        ret->go_sleep();
     }
    T t= ret->Pop();
    ret->unlock();
    t();
    cout<< t.getresult()<<endl;
    
   }

}
void Push(T t)
{
  lock();
  _st.push(t);
  weakup();
  unlock();

}
T Pop()
{

 T t=_st.front();
 _st.pop();
 return t;

}

private:
vector<threadpooldata> _threads;
queue<T> _st;
pthread_mutex_t _mutex;
pthread_cond_t _cond;

};